import Vue from 'vue'
import Vuex from 'vuex'

// 使用Vuex插件
Vue.use(Vuex)

// mdA模块  =>  默认情况下子模块中state会对应模块名称,挂载到父模块(父store)下, getters,mutations,actions中的属性和方法会挂载到根store (取值直接从根store中取即可 -> 缺点: getters,mutations,actions全都挂载在根store,依存关系不明显)
var mdA = {
  // namespaced:false,
  state: function () {
    return {
      user: "a123123",
      token: "aaaaaaaaaaaaaaaaaaaaaaaaa"
    }
  },
  getters: {
    // state 形参 =>  默认指向当前模块中的state对象
    // getters 形参 => 默认指向当前模块中的getters对象
    isLogin: function (state, getters) {
      console.log(state, getters);
      return state.user && state.token ? true : false;
    }
  },
  mutations: {
    // state 形参 =>  默认指向当前模块中的state对象
    // payload   => 调用此方法时传入的数据  commit("updateInfo",{user,token})
    updateInfo: function (state, payload) {
      var { user, token } = payload;

      if (user) {
        state.user = user;
      }
      if (token) {
        state.token = token;
      }

    }
  },
  actions: {
    // 和当前module(子store实例) 有相同属性和方法的新对象
    loginAndUpdateInfo: function (context, payload) {

      var { commit } = context;
      console.log("接收的参数", payload);

      return new Promise(function (resolve) {

        setTimeout(() => {
          commit("updateInfo", {
            user: "b123123",
            token: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
          })
          resolve(true);
        }, 1000);

      })
    }

  },
  modules: {
    // mdA 下的子模块 mdA_1
    mdA_1: {
      state() {
        return {
          a1: 10,
          b1: 20,
        }
      },
      getters: {
        both_mdA_1(state) {
          return state.a1 + state.b1;
        }
      }
    }
  }

}



var mdB = {
  namespaced: true,  // 是否设置命名空间(默认false 如果设置为true  state,getters,mutations,actions都会对应模块名称挂载到父store)   模块划分的比较精准  -> 取值比较麻烦
  state: function () {
    return {
      user: "a123123",
      token: "aaaaaaaaaaaaaaaaaaaaaaaaa"
    }
  },
  getters: {
    // state 形参 =>  默认指向当前模块中的state对象
    // getters 形参 => 默认指向当前模块中的getters对象
    // rootState   形参 =>  默认指向根模块中的state对象
    // rootGetters  形参 => 默认指向根模块中的getters对象
    isLogin: function (state, getters) {
      console.log(state, getters);
      return state.user && state.token ? true : false;
    },
    // 当前模块 mdB -> 访问根Store中的数据
    lookBoth: function (state, getters, rootState) {
      // console.log("rootState", rootState);
      // console.log("rootGetters", rootGetters);
      return rootState.a + rootState.b;
    },
    lookBothDouble: function (state, getters, rootState, rootGetters) {
      console.log("rootState", rootState);
      console.log("rootGetters", rootGetters);

      // 当前模块访问根Store中的state和getters
      // console.log(rootState.a);
      // console.log(rootState.b);
      // console.log(rootGetters.doubleA);
      // console.log(rootGetters.doubleB);

      // 通过 rootState, rootGetters 访问其他模块(mdB->假装一下是其他模块)
      // console.log(rootState.mdB.user);
      // console.log(rootState.mdB.token);
      // console.log(rootGetters["mdB/isLogin"]);
      // console.log(rootGetters["mdB/lookBoth"]);

      // 通过根模块访问 rootState, rootGetters 访问其他模块的子模块(mdB->假装一下是其他模块)
      // console.log(rootState.mdB.mdB_1.a1);
      // console.log(rootState.mdB.mdB_1.b1);
      // console.log(rootGetters["mdB/mdB_1/both_mdB_1"]);


      return rootGetters.doubleA + rootGetters.doubleB;
    }
  },
  mutations: {
    // state 形参 =>  默认指向当前模块中的state对象
    // payload   => 调用此方法时传入的数据  commit("updateInfo",{user,token})
    updateInfo: function (state, payload) {
      var { user, token } = payload;

      if (user) {
        state.user = user;
      }
      if (token) {
        state.token = token;
      }

    }
  },
  actions: {
    // context 和当前module(子store实例) 有相同属性和方法的新对象
     // context => {commit,dispatch,state,getters,rootState,rootGetters}
    loginAndUpdateInfo: function (context, payload) {

      var { commit } = context;
      console.log("接收的参数", payload);

      return new Promise(function (resolve) {

        setTimeout(() => {
          commit("updateInfo", {
            user: "b123123",
            token: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
          })
          resolve(true);
        }, 1000);

       
      })
    },

    addBoth: function (context, payload) {
      // context => {commit,dispatch,state,getters,rootState,rootGetters}

      // commit ,dispatch 可以对应名称调用 当前模块的mutations和actions方法,
      // 也可以调用全局模块的方法 (如果调用根模块的需要添加第三参数 {root:true})
      // 也可以对应模块名称和方法 调用子模块的方法
      // 其他模块建议通过根模块访问
      
      var { commit } = context;
      console.log("context", context);
      console.log("接收的参数", payload);

      // 访问当前模块
      commit("updateInfo",{user:"dd123123",token:"ccccccccccccccccccccc"})
      
      // 调用全局的,需要添加第三参数 {root:true},  如果不加 默认是局部的
      commit("addA", payload.a, { root: true });
      commit("addB", null, { root: true });
      
      // 访问子模块的  ()
      // commit("mdB_1/increaseBoth", null);  //当前模块(mdB)访问子模块(mdB_1)

      // 根模块逐层访问
      commit("mdB/mdB_1/increaseBoth", null, { root: true });  //根模块逐层访问
    }

  },
  modules: {
    // mdA 下的子模块 mdA_1
    mdB_1: {
      namespaced: true,
      state() {
        return {
          a1: 10,
          b1: 20,
        }
      },
      getters: {
        both_mdB_1(state) {
          return state.a1 + state.b1;
        }
      },
      mutations: {
        increaseBoth(state) {
          state.a1++
          state.b1++
        }
      }
    }
  }

}




// 创建store实例
export default new Vuex.Store({
  state: {
    a: 1,
    b: 2,
  },
  getters: {
    // state 形参 =>  通过state获取state对象中的数据 
    // getters 形参 =>  通过getters获取getters对象中的数据   (可以复用计算属性)
    doubleA: function (state) {
      return state.a * 2;
    },
    tripleA: function (state) {
      return state.a * 3;
    },
    doubleB: function (state) {
      return state.b * 2;
    },
    tripleB: function (state) {
      return state.b * 3;
    },
    // doubleBoth =  doubleA + doubleB  ( doubleA , doubleB计算属性)
    both: function (state) {
      return state.a + state.b;
    },
    doubleBoth: function (state, getters) {
      // return state.a * 2 + state.b * 2;   // low  => 没有复用doubleA , doubleB
      return getters.doubleA + getters.doubleB;
    }

  },
  mutations: {
    // state 形参 =>  通过state获取state对象中的数据 
    // payload  => 载荷,在组件中调用此方法时可以传递一些数据  
    //             如何调用 =>  commit("updateA",10)
    addA: function (state) {
      state.a++;
    },
    reduceA: function (state) {
      state.a--;
    },
    updateA: function (state, payload) {
      console.log("updateA", payload);
      state.a = payload;
    },
    addB: function (state) {
      state.b++;
    },
    reduceB: function (state) {
      state.b--;
    },
    updateB: function (state, payload) {
      console.log("updateB", payload);
      state.b = payload;
    },
    // mutations的方法中 不能直接使用另一个方法 =>在actions中实现
    // addBoth:function(state,payload,arg){
    //   console.log(11111,state,payload,arg);
    // }
  },
  actions: {
    // action用于存放异步操作 -> 在异步操作结束之后,再掉头mutations中的方法修改数据
    // context  => 和store实例用相同属性和方法的对象 (新对象)
    // payload  => actions中的方法被调用时,也可以接收参数



    // 简单写法 => 在异步操作结束之后,再调用mutations中的方法修改数据 (不能知道异步操作什么时候结束)
    addA_Async: function (context, payload) {
      // context =>  {state,getters,commit,dispatch}
      console.log("context", context);
      console.log("payload", payload);

      var { commit } = context;
      setTimeout(() => {
        commit("addA", payload);
      }, 1000);
    },
    addB_Async: function (context, payload) {
      // context =>  {state,getters,commit,dispatch}
      console.log("context", context);
      console.log("payload", payload);

      var { commit } = context;
      setTimeout(() => {
        commit("addB", payload);
      }, 1000);
    },

    // Promise改写版本 =>  返回一个Promise实例(pending)  -> 在异步操作结束之后,再调用mutations中的方法修改数据(将Promise实例的状态改为fulfilled)
    addA_Async_Pro: function (context, payload) {
      // context =>  {state,getters,commit,dispatch}

      return new Promise(function (resolve) {
        console.log("context", context);
        console.log("payload", payload);
        var { commit } = context;
        setTimeout(() => {
          commit("addA", payload);
          resolve(true);
        }, 1000);
      })
    },
    addB_Async_Pro: function (context, payload) {
      // context =>  {state,getters,commit,dispatch}

      return new Promise(function (resolve) {
        console.log("context", context);
        console.log("payload", payload);
        var { commit } = context;
        setTimeout(() => {
          commit("addB", payload);
          resolve(true);
        }, 1000);
      })
    },

    // action中复用mutations中的多个方法
    addBoth: function (context, payload) {
      // context =>  {state,getters,commit,dispatch}
      console.log("参数", payload);
      var { commit } = context;
      commit("addA", payload.a);
      commit("addB", payload.b);
    },

    // action中复用actions中的多个方法
    addBoth_Async: function (context, payload) {
      // context =>  {state,getters,commit,dispatch}
      console.log("参数", payload);
      var { dispatch } = context;
      dispatch("addA_Async", payload.a);
      dispatch("addB_Async", payload.b);
    },

    addBoth_Async_Pro: async function (context, payload) {
      // context =>  {state,getters,commit,dispatch}
      console.log("参数", payload);
      var { dispatch } = context;
      await dispatch("addA_Async_Pro", payload.a)
      await dispatch("addB_Async_Pro", payload.b);
      alert("A和B更新完毕")
    }


  },
  modules: {
    // 键名 => 模块的名称
    // 键值 => 模块的配置对象(子模块/store)
    mdA: mdA,
    mdB: mdB,
  }
})
